package com.wh.wisdomsite.xbox.utils.json;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

/**
 * JSON工具类(自定义JSON解析类)
 * @Package com.wh.wisdomsite.xbox.utils.json
 * @author 谢泽鹏
 * @date 2014年10月8日 下午4:02:14
 * @Copyright 个人版权所有
 * @Company 贵州万华科技有限公司Copyright (c) 2014
 * @version V1.0
 */
public final class JsonUtil {

    private static final Log logger = LogFactory.getLog(JsonUtil.class);
	
	/**
	 * 为了统一处理任意的 Java 对象，编写一个入口方法 Json2All(Object)，能够将任意的 Java 对象编码为 JSON 格式
	 * @param o
	 * @return
	 */
	public static String Json2All(final Object o) {
		if (o == null) {
			return "null";
		}
		if (o instanceof String) {
			return Json2string((String) o);
		}
		if (o instanceof Boolean) {
			return Json2boolean((Boolean) o);
		}
		if(o instanceof Collection) {
			return Json2collection((Collection) o);
		}
		if(o instanceof Map) {
			return Json2map((Map) o);
		}
		if (o instanceof Number) {
			return Json2number((Number) o);
		}
		if (o instanceof Object[]) {
			return Json2array((Object[]) o);
		}
		if (o instanceof int[]) {
			return Json2intArray((int[]) o);
		}
		if (o instanceof boolean[]) {
			return Json2booleanArray((boolean[]) o);
		}
		if (o instanceof long[]) {
			return Json2longArray((long[]) o);
		}
		if (o instanceof float[]) {
			return Json2floatArray((float[]) o);
		}
		if (o instanceof double[]) {
			return Json2doubleArray((double[]) o);
		}
		if (o instanceof short[]) {
			return Json2shortArray((short[]) o);
		}
		if (o instanceof byte[]) {
			return Json2byteArray((byte[]) o);
		}
		if (o instanceof Object) {
			return Json2object(o);
		}
		throw new RuntimeException("不支持的类型: " + o.getClass().getName());
	}

	/**
	 * 将 String 对象编码为 JSON 格式， 只需处理好特殊字符
	 * @param s  String 对象    
	 * @return JSON格式
	 */
	public static String Json2string(final String s) {
		final StringBuilder sb = new StringBuilder(s.length() + 20);
		sb.append('"');
		for (int i = 0; i < s.length(); i++) {
			final char c = s.charAt(i);
			switch (c) {
			case '"':
				sb.append("\\\"");
				break;
			case '\\':
				sb.append("\\\\");
				break;
			case '/':
				sb.append("\\/");
				break;
			case '\b':
				sb.append("\\b");
				break;
			case '\f':
				sb.append("\\f");
				break;
			case '\n':
				sb.append("\\n");
				break;
			case '\r':
				sb.append("\\r");
				break;
			case '\t':
				sb.append("\\t");
				break;
			default:
				sb.append(c);
			}
		}
		sb.append('"');
		logger.info("Json2string->>" + sb.toString());
		return sb.toString();
	}

	/**
	 * 将 Number 表示为 JSON格式
	 * @param number Number
	 * @return JSON格式
	 */
	public static String Json2number(final Number number) {
		logger.info("Json2number->>" +  "\""+number.toString()+"\"");
		return "\""+number.toString()+"\"";
	}

	/**
	 * 将Boolean 表示为JSON格式
	 * @param bool  Boolean   
	 * @return JSON格式
	 */
	public static String Json2boolean(final Boolean bool) {
		logger.info("Json2boolean->>" +  bool.toString());
		return bool.toString();
	}

	
	/**
	 * 将Collection 编码为JSON格式(List，Set)
	 * @param c
	 * @return
	 */
	public static String Json2collection(final Collection<Object> c) {
		final Object[] arrObj = c.toArray();
		String str =  Json2All(arrObj);
		logger.info("Json2collection->>" +  str);
		return str;
	}

	/**
	 * 将 Map<String, Object>编码为JSON格式
	 * @param map
	 * @return
	 */
	public static String Json2map(final Map<String, Object> map) {
		if (map.isEmpty()) {
			return "{}";
		}
		final StringBuilder sb = new StringBuilder(map.size() << 4);// 4次方
		sb.append("{");
		final Set<String> keys = map.keySet();
		for (final String key : keys) {
			final Object value = map.get(key);
			sb.append('"');
			//不能包含特殊字符
			sb.append(key);
			sb.append('"');
			sb.append(':');
			//循环引用的对象会引发无限递归
			sb.append(Json2All(value));
			sb.append(",");
		}
		// 将最后的','变为'}'
		sb.setCharAt(sb.length() - 1, '}');
		logger.info("Json2map->>" + sb.toString());
		return sb.toString();
	}
	
	/**
	 * 将数组编码为 JSON 格式
	 * @param array 数组 
	 * @return
	 */
	public static String Json2array(final Object[] array) {
		if (array.length == 0) {
			return "[]";
		}
		final StringBuilder sb = new StringBuilder(array.length << 4);// 4次方
		sb.append('[');
		for (final Object o : array) {
			sb.append(Json2All(o));
			sb.append(',');
		}
		sb.setCharAt(sb.length() - 1, ']');
		logger.info("Json2array->>" + sb.toString());
		return sb.toString();
	}

	/**
	 * @Description 将INT类型数组编码为 JSON 格式
	 * @date 2014年10月11日 上午9:29:35
	 * @param intArray 
	 * @return String   
	 */
	public static String Json2intArray(final int[] intArray) {
		if (intArray.length == 0) {
			return "[]";
		}
		final StringBuilder sb = new StringBuilder(intArray.length << 4);// 4次方
		sb.append('[');
		for (final int o : intArray) {
			sb.append(Integer.toBinaryString(o));
			sb.append(',');
		}
		sb.setCharAt(sb.length() - 1, ']');
		logger.info("Json2intArray->>" + sb.toString());
		return sb.toString();
	}

	/**
	 * @Description 将LONG类型数组编码为 JSON 格式
	 * @date 2014年10月11日 上午9:29:35
	 * @param longArray 
	 * @return String   
	 */
	public static String Json2longArray(final long[] longArray) {
		if (longArray.length == 0) {
			return "[]";
		}
		final StringBuilder sb = new StringBuilder(longArray.length << 4);
		sb.append('[');
		for (final long o : longArray) {
			sb.append(Long.toString(o));
			sb.append(',');
		}
		// set last "," to "]":
		sb.setCharAt(sb.length() - 1, ']');
		logger.info("Json2longArray->>" + sb.toString());
		return sb.toString();
	}

	/**
	 * @Description 将Boolean类型数组编码为 JSON 格式
	 * @date 2014年10月11日 上午9:29:35
	 * @param booleanArray 
	 * @return String   
	 */
	public static String Json2booleanArray(final boolean[] booleanArray) {
		if (booleanArray.length == 0) {
			return "[]";
		}
		final StringBuilder sb = new StringBuilder(booleanArray.length << 4);
		sb.append('[');
		for (final boolean o : booleanArray) {
			sb.append(Boolean.toString(o));
			sb.append(',');
		}
		// set last "," to "]":
		sb.setCharAt(sb.length() - 1, ']');
		logger.info("Json2booleanArray->>" + sb.toString());
		return sb.toString();
	}

	/**
	 * @Description 将Float类型数组编码为 JSON 格式
	 * @date 2014年10月11日 上午9:29:35
	 * @author xiezepeng
	 * @param floatArray 
	 * @return String   
	 */
	public static String Json2floatArray(final float[] floatArray) {
		if (floatArray.length == 0) {
			return "[]";
		}
		final StringBuilder sb = new StringBuilder(floatArray.length << 4);
		sb.append('[');
		for (final float o : floatArray) {
			sb.append(Float.toString(o));
			sb.append(',');
		}
		// set last "," to "]":
		sb.setCharAt(sb.length() - 1, ']');
		logger.info("Json2floatArray->>" + sb.toString());
		return sb.toString();
	}

	
	/**
	 * @Description 将Double类型数组编码为 JSON 格式
	 * @date 2014年10月11日 上午10:08:21
	 * @author xiezepeng
	 * @param doubleArray
	 * @return String   
	 */
	public static String Json2doubleArray(final double[] doubleArray) {
		if (doubleArray.length == 0) {
			return "[]";
		}
		final StringBuilder sb = new StringBuilder(doubleArray.length << 4);
		sb.append('[');
		for (final double o : doubleArray) {
			sb.append(Double.toString(o));
			sb.append(',');
		}
		// set last "," to "]":
		sb.setCharAt(sb.length() - 1, ']');
		logger.info("Json2doubleArray->>" + sb.toString());
		return sb.toString();
	}

	
	
	/**
	 * @Description 将Short类型数组编码为 JSON 格式
	 * @date 2014年10月11日 上午10:08:21
	 * @author xiezepeng
	 * @param shortArray
	 * @return String   
	 */
	public static String Json2shortArray(final short[] shortArray) {
		if (shortArray.length == 0) {
			return "[]";
		}
		final StringBuilder sb = new StringBuilder(shortArray.length << 4);
		sb.append('[');
		for (final short o : shortArray) {
			sb.append(Short.toString(o));
			sb.append(',');
		}
		// set last "," to "]":
		sb.setCharAt(sb.length() - 1, ']');
		logger.info("shortArray->>" + sb.toString());
		return sb.toString();
	}


	/**
	 * @Description 将Byte类型数组编码为 JSON 格式
	 * @date 2014年10月11日 上午10:08:21
	 * @author xiezepeng
	 * @param byteArray
	 * @return String   
	 */
	public static String Json2byteArray(final byte[] byteArray) {
		if (byteArray.length == 0) {
			return "[]";
		}
		final StringBuilder sb = new StringBuilder(byteArray.length << 4);
		sb.append('[');
		for (final byte o : byteArray) {
			sb.append(Byte.toString(o));
			sb.append(',');
		}
		// set last "," to "]":
		sb.setCharAt(sb.length() - 1, ']');
		logger.info("Json2byteArray->>" + sb.toString());
		return sb.toString();
	}

	
	/**
	 * @Description 将Byte类型数组编码为 JSON 格式
	 * @date 2014年10月11日 上午10:08:21
	 * @author xiezepeng
	 * @param  object
	 * @return String   
	 */
	public static String Json2object(final Object object) {
		String str = null;
		//数据检查
		if (object == null) {
			return "{}";
		}
		//方法数组
		final Method[] methods = object.getClass().getMethods();
		//4次方
		final StringBuilder sb = new StringBuilder(methods.length << 4);
		sb.append('{');

		for (final Method method : methods) {
			try {
				final String name = method.getName();
				String key = "";
				if (name.startsWith("get")) {
					key = name.substring(3);
					//防止死循环
					final String[] arrs = { "Class" };
					boolean b1 = false;
					for (final String s : arrs) {
						if (s.equals(key)) {
							b1 = true;
							continue;
						}
					}
					if (b1) {
						//防止死循环
						continue;
					}
				} else if (name.startsWith("is")) {
					key = name.substring(2);
				}
				if (key.length() > 0 && Character.isUpperCase(key.charAt(0)) && method.getParameterTypes().length == 0) {
					if (key.length() == 1) {
						key = key.toLowerCase();
					} else if (!Character.isUpperCase(key.charAt(1))) {
						key = key.substring(0, 1).toLowerCase() + key.substring(1);
					}
					final Object elementObj = method.invoke(object, new Object[0]);
					sb.append('"');
					sb.append(key);
					sb.append('"');
					sb.append(':');
					sb.append(Json2All(elementObj));
					sb.append(",");
				}
			} catch (Exception e) {
                logger.error("Json2object->>在将bean封装成JSON格式时异常：" + e.getMessage().toString());
				throw new RuntimeException("在将bean封装成JSON格式时异常：" + e.getMessage(), e);				
			}
		}
		if (sb.length() == 1) {
			str = object.toString();
		} else {
			sb.setCharAt(sb.length() - 1, '}');
			str = sb.toString();
		}
		logger.info("Json2object->>" + str);
		return str;
		
	}




}
